﻿using FluentFTP;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace WinFormsApp1
{
    public class FluentFtpHelper
    {
        /// <summary>
        /// 检测Ftp服务器是否在线
        /// </summary>
        /// <returns></returns>
        public static bool CheckFtpServerOnline()
        {
            try
            {
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(Form1.str_url);
                request.Credentials = new NetworkCredential(Form1.FtpUser, Form1.FtpPassword);
                request.Method = WebRequestMethods.Ftp.ListDirectory; // 尝试列出目录
                request.Timeout = 5000; // 超时设为5秒

                using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
                {
                    // 若响应状态码为200系列（如CommandOK），则服务器在线
                    return (int)response.StatusCode >= 100;
                }
            }
            catch (WebException ex)
            {
                // 连接失败或超时视为服务器离线
                Form1.log.Error(ex);
                return false;
            }
        }

        public static async Task<int> UploadAsync(string picFullName, string ftpRemotePath, string picName)
        {
            try
            {
                string baseUri = Form1.str_url;
                var uri = new Uri(baseUri);
                string remoteFileName = $"{picName}.jpg";

                using (var client = new FtpClient(uri.Host, uri.Port, Form1.FtpUser, Form1.FtpPassword))
                {
                    // 配置客户端参数
                    client.EncryptionMode = FtpEncryptionMode.None; // 不加密
                    client.DataConnectionType = FtpDataConnectionType.AutoPassive; // 自动选择被动模式
                    client.RetryAttempts = 3; // 失败重试次数

                    // 连接到服务器
                    await client.ConnectAsync();
                    Form1.log.Info($"已连接到FTP服务器: {uri.Host}:{uri.Port}");

                    // 确保远程目录存在（递归创建）
                    await EnsureFtpDirectoryExistAsync(client, ftpRemotePath);

                    // 上传文件到指定路径
                    bool status = await client.UploadFileAsync(
                        localPath: picFullName,
                        remotePath: $"{ftpRemotePath}/{remoteFileName}".Replace("//", "/"), // 清理双斜杠
                        existsMode: FtpRemoteExists.Overwrite // 覆盖已存在文件
                    );

                    if (status)
                    {
                        Form1.log.Info($"上传成功: {ftpRemotePath}/{remoteFileName} ({new FileInfo(picFullName).Length}字节)");
                        return 1;
                    }

                    Form1.log.Error($"上传失败: {status}");
                    return -1;
                }
            }
            catch (Exception ex)
            {
                Form1.log.Error($"上传过程中出错: {ex.Message}");
                return -1;
            }
        }

        private static async Task EnsureFtpDirectoryExistAsync(FtpClient client, string remoteDirectory)
        {
            try
            {
                // 1. 标准化路径格式（关键修复）
                remoteDirectory = remoteDirectory.Replace("\\", "/").Trim('/');

                // 2. 打印当前工作目录（用于定位）
                string workingDir = await client.GetWorkingDirectoryAsync();
                Form1.log.Debug($"当前工作目录: {workingDir}");

                // 3. 检查目录是否存在（带详细日志）
                bool existsBefore = await client.DirectoryExistsAsync(remoteDirectory);
                Form1.log.Debug($"目录存在检查: {existsBefore} [{remoteDirectory}]");

                if (existsBefore)
                {
                    Form1.log.Debug($"目录已存在: {remoteDirectory}");
                    return;
                }

                // 4. 创建目录（添加详细跟踪）
                Form1.log.Info($"开始创建目录: {remoteDirectory}");
                await client.CreateDirectoryAsync(remoteDirectory, force: true);

                // 5. 添加延迟并重新检查（处理服务器刷新延迟）
                await Task.Delay(1000); // 等待1秒让服务器刷新

                // 6. 二次验证目录是否真正创建
                bool existsAfter = await client.DirectoryExistsAsync(remoteDirectory);
                Form1.log.Info($"目录创建验证: {existsAfter} [{remoteDirectory}]");

                if (!existsAfter)
                {
                    // 7. 尝试列出父目录内容（调试用）
                    string parentDir = Path.GetDirectoryName(remoteDirectory)?.Replace("\\", "/") ?? "";
                    if (!string.IsNullOrEmpty(parentDir))
                    {
                        var items = await client.GetListingAsync(parentDir);
                        Form1.log.Warn($"父目录内容 [{parentDir}]: {string.Join(", ", items.Select(i => i.Name))}");
                    }

                    throw new Exception($"目录创建失败: {remoteDirectory}");
                }

                Form1.log.Info($"已创建目录: {remoteDirectory}");
            }
            catch (FtpCommandException ex) when (ex.CompletionCode == "550")
            {
                Form1.log.Debug($"捕获550异常: {ex.Message}");

                // 更精确的目录存在检查
                bool exists = await client.DirectoryExistsAsync(remoteDirectory);
                Form1.log.Debug($"550异常后目录存在检查: {exists}");

                if (exists)
                {
                    Form1.log.Debug($"目录已存在（并行创建冲突）: {remoteDirectory}");
                }
                else
                {
                    Form1.log.Error($"目录创建失败: {ex.Message}");

                    // 添加详细的错误诊断
                    Form1.log.Error($"FTP响应: {ex.Message}");
                    Form1.log.Error($"错误代码: {ex.CompletionCode}");

                    throw;
                }
            }
            catch (Exception ex)
            {
                Form1.log.Error($"目录创建错误: {ex.Message}");

                // 记录完整堆栈跟踪
                Form1.log.Debug($"堆栈跟踪: {ex.StackTrace}");
                throw;
            }
        }
    }
}
